package com.jt.www.biz.order_pc.service.impl;

import com.jt.www.biz.order_pc.service.PreviewService;
import com.jt.www.domain.vo.BmsCommissionVO;
import com.jt.www.domain.vo.BmsPaymentVO;
import com.jt.www.domain.vo.BmsSettlementVO;
import com.jt.www.enums.endorse.PolicyTypeEnum;
import com.jt.www.enums.extend.SchoolTypeEnum;
import com.jt.www.exception.BizException;
import com.jt.www.model.mail.vo.AccountVo;
import com.jt.www.model.mail.vo.JtBranchAccountVo;
import com.jt.www.model.param.endorse.AppDetailProParam;
import com.jt.www.model.remote.ins.CommonExtendVo;
import com.jt.www.model.remote.user.EduAuthenInfoDetails;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.model.vo.EduOrgsVO;
import com.jt.www.model.vo.endorse.AppDetailProVo;
import com.jt.www.model.vo.endorse.DetailVo;
import com.jt.www.model.vo.sdCheck.*;
import com.jt.www.model.vo.woxuebao.OrgElementVO;
import com.jt.www.remote.BmsClient;
import com.jt.www.remote.UserClient;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.util.DateUtils;
import com.jt.www.util.JsonUtil;
import com.jt.www.util.MoneyUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by shaoyn on 2019/12/05.
 */
@Service
public class PreviewServiceImpl implements PreviewService {

    public static final Logger log = LoggerFactory.getLogger(PreviewServiceImpl.class);
    //机构类型
    private final static String CORPORATION_ENT = "edu_02";
    //渠道编码
    private final static String CHANNEL_CODE = "edu";
    //
    private final static Integer PAGE_NUM = 1;
    //渠道编码
    private final static Integer PAGE_SIZE = 20;
    @Autowired
    InsClient insClient;
    @Autowired
    UserClient userClient;
    @Autowired
    BmsClient bmsClient;

    //判断获取的值是否是数字
    public static boolean isNumeric(String str) {
        for (int i = str.length(); --i >= 0; ) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    @Override
    public AppDetailProVo searchAppDetailPro(AppDetailProParam param) {
        try {
            ResponseEntity<GenericDataResponse<AppDetailProVo>> result = insClient.searchAppDetailPro(param);
            if (result.getStatusCode().equals(HttpStatus.OK)) {
                return result.getBody().getData();
            }
        } catch (Exception e) {
        }
        return new AppDetailProVo();
    }

    @Override
    public ResponseEntity<GenericDataResponse<JtBranchAccountVo>> branchAccount(String areaCode, String channelNo, String productCode) {
        ResponseEntity<GenericDataResponse<JtBranchAccountVo>> jtBranch = null;
        try {
            jtBranch = userClient.branchAccount(areaCode, channelNo, productCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jtBranch;
    }

    private EduOrgsVO queryAuthentEduInfo(String userCode) {
        try {
            EduOrgsVO user = new EduOrgsVO();

            if (StringUtils.isBlank(userCode)) {
                throw new BizException("投保人userCode为空");
            }

            ResponseEntity<GenericDataResponse<EduAuthenInfoDetails>> result = userClient.queryAuthentEduInfo(userCode);
            if (result == null) {
                throw new BizException("用户信息调用失败");
            }
            EduAuthenInfoDetails eduAuthenInfoDetails = result.getBody().getData();
            if (eduAuthenInfoDetails == null) {
                throw new BizException("找不到该用户");
            }
            List<OrgElementVO> custOrganizationElementList = eduAuthenInfoDetails.getCustOrganizationElementList();
            for (OrgElementVO orgElementVO : custOrganizationElementList) {
                if (orgElementVO.getElementCode().equals("linkManEmail")) {
                    user.setLinkManEmail(orgElementVO.getElementValues());
                } else if (orgElementVO.getElementCode().equals("linkManPhone")) {
                    user.setLinkManPhone(orgElementVO.getElementValues());
                } else if (orgElementVO.getElementCode().equals("linkManName")) {
                    user.setLinkManName(orgElementVO.getElementValues());
                }
            }
            return user;
        } catch (Exception e) {
            log.error("下载投保单pdf异常{}", e);
            return null;
        }
    }

    @Override
    public ResponseEntity<GenericListResponse<DetailVo>> insuranceObjects(String appCode) {
        try {
            ResponseEntity<GenericListResponse<DetailVo>> appDetailPro = insClient.insuranceObjects(appCode);
            return appDetailPro;
        } catch (Exception e) {
            log.error("根据投保单号查询标的列表异常 appCode:{}", appCode);
            e.printStackTrace();
        }
        return null;
    }

    private void getAccountList(Model model, AppDetailProVo appDetailProVo) {
        //调用用户中心 根据省市区查询机构账户信息
        ResponseEntity<GenericDataResponse<JtBranchAccountVo>> jtBranchAccount = null;
        try {
            jtBranchAccount = branchAccount(appDetailProVo.getInsuredList().get(0).getCorporation().getCountyCode(), "edu", appDetailProVo.getProductCode());
        } catch (Exception e) {
            log.error("根据省市区查询机构账户信息失败===》投保单号：" + appDetailProVo.getApplicationFormCode(), e);
            e.printStackTrace();
        }
        GenericDataResponse<JtBranchAccountVo> body = jtBranchAccount.getBody();
        if (null != body && null != body.getData()) {
            JtBranchAccountVo data = body.getData();
            List<AccountVo> accountVoList = data.getAccountVoList();
            for (AccountVo account : accountVoList) {
                //户名
                String bankName = account.getBankName();
                //开户行
                String bankAccountNameaccount = account.getBankAccountName();
                //账号
                String bankAccountNo = account.getBankAccountNo();
                model.addAttribute("bankName", bankName);
                model.addAttribute("bankAccountNameaccount", bankAccountNameaccount);
                model.addAttribute("bankAccountNo", bankAccountNo);
            }
        }
    }


    @Override
    public String appForm(AppDetailProParam param, Model model, String findCode) {
        AppDetailProVo appDetailProVo = searchAppDetailPro(param);
        log.info("投保单预览{} 查询投保单详情完成 投保单号{}", findCode, param.getAppCode());

        //获取到投保中心金额进行大小写转换
        String premiumStr = MoneyUtil.CNValueOf(appDetailProVo.getAfterPrem());
        model.addAttribute("premiumStr", premiumStr);
        model.addAttribute("ins", appDetailProVo);
        log.info("投保单预览{} 金额大小写转换完成 投保单号{}", findCode, param.getAppCode());

        //计算保险期间 月数
        if (StringUtils.isNotBlank(appDetailProVo.getStartDate()) && StringUtils.isNotBlank(appDetailProVo.getEndDate())) {
            String startDate = appDetailProVo.getStartDate();
            String endDate = appDetailProVo.getEndDate();
            int months = DateUtils.getMonthDiff(
                    DateUtils.str2Date(startDate, DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS),
                    DateUtils.str2Date(endDate, DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));

            model.addAttribute("months", months);
            log.info("投保单预览{} 计算保险期间月数{} 投保单号{}", findCode, months, param.getAppCode());
        }

        //获取基础信息扩展字段
        List<InsuredForProVO> insuredList = appDetailProVo.getInsuredList();
        log.info("投保单预览{} 获取被保险人列表，被保险人个数{} 投保单号{}", findCode, insuredList.size(), param.getAppCode());
        if (insuredList != null && insuredList.size() > 0) {
            for (InsuredForProVO insuredForProVO : insuredList) {
                CorporationForProVO corporationForProVO = insuredForProVO.getCorporation();
                List<ExtendForProVO> extendForProVOS = corporationForProVO.getExtendList();
                if (corporationForProVO != null && extendForProVOS.size() > 0) {
                    for (ExtendForProVO extendForProVO : extendForProVOS) {
                        //学校性质 学校类型 学制
                        String key = extendForProVO.getKey();
                        String value = extendForProVO.getValue();
                        if (key.equals("S_I_000089")) {
                            //映射学校类型名称
                            String schoolTypeName = SchoolTypeEnum.getMsgByCode(value);
                            model.addAttribute(key, schoolTypeName);
                        } else {
                            model.addAttribute(key, value);
                        }

                    }
                }

                List<CommonInsuranceObjectVo> insuranceObjectVos = insuredForProVO.getInsuranceObjectVos();
                if (insuranceObjectVos != null && insuranceObjectVos.size() > 0) {
                    //获取各个产品多个扩展字段,比如分年级,求总人数
                    Integer insuredNumber = 0;
                    for (CommonInsuranceObjectVo commonInsuranceObjectVo : insuranceObjectVos) {
                        model.addAttribute("carNumber", commonInsuranceObjectVo.getObjectId());
                        if (commonInsuranceObjectVo.getCommonExtendVoList().size() > 0) {
                            for (CommonExtendVo commonExtendVo : commonInsuranceObjectVo.getCommonExtendVoList()) {
                                String key = commonExtendVo.getFieldCode();
                                String value = commonExtendVo.getFieldValues();
                                model.addAttribute(key, value);
                                //判断值是否为数字或者不为空
                                if (appDetailProVo.getProductCode().equals(PolicyTypeEnum.HN_SZX.getProductCode())) {
                                    if (StringUtils.isNotEmpty(value) && isNumeric(value))
                                        insuredNumber += Integer.valueOf(value);
                                }
                                if (appDetailProVo.getProductCode().equals(PolicyTypeEnum.HN_XZX.getProductCode())) {
                                    if (key.equals("S_O_000021")) {
                                        insuredNumber = Integer.valueOf(value);
                                    }

                                }

                            }

                        }
                    }
                    log.info("投保人数{}", insuredNumber);
                    model.addAttribute("insuredNumber", insuredNumber);
                }
            }
        }

        //获取方案编码
        List<Map<String, Object>> riskList = appDetailProVo.getRiskList();
        log.info("投保单预览{} 获取方案列表，方案个数{} 投保单号{}", findCode, riskList.size(), param.getAppCode());
        for (int i = 0; i < riskList.size(); i++) {
            Object value = riskList.get(i).get("programCode");
            Object riskCode = riskList.get(i).get("riskCode");
            Object premValue = riskList.get(i).get("afterPrem");
            model.addAttribute("programCode" + i, value);
            model.addAttribute("programCode" + i + "prem", premValue);
            model.addAttribute("riskCode" + i, riskCode);
        }
        model.addAttribute("riskList", riskList);
        //获取投保人数
        List<PremiunFactorVo> premiunFactorVos = appDetailProVo.getPremiunFactorVos();
        log.info("投保单预览{} 获取投保人数PremiunFactorVos个数{} 投保单号{}", findCode, premiunFactorVos, param.getAppCode());
        if (premiunFactorVos != null && premiunFactorVos.size() > 0) {

            for (PremiunFactorVo premiunFactorVo : premiunFactorVos) {
                if (StringUtils.isNotBlank(premiunFactorVo.getFieldCode())) {
                    if (premiunFactorVo.getFieldCode().equals("19YZ159166")) {
                        String amountStudent = premiunFactorVo.getFieldValue();
                        model.addAttribute("amountStudent", amountStudent);
                    }
                    String filedValue = premiunFactorVo.getFieldValue();
                    model.addAttribute("fieldCode" + premiunFactorVo.getFieldCode(), filedValue);
                }

            }
        }
        //获取出单公司信息
        List<InsuranceCompanyVO> insuranceCompanyVOS = appDetailProVo.getInsuranceCompanyVOS();
        log.info("投保单预览{} 获取共保公司个数{} 投保单号{}", findCode, JsonUtil.object2Json(insuranceCompanyVOS), param.getAppCode());
        if (insuranceCompanyVOS != null && insuranceCompanyVOS.size() > 0) {
            for (InsuranceCompanyVO insureTrackVO : insuranceCompanyVOS) {
                if (StringUtils.isNotBlank(insureTrackVO.getRole2()) && ("01".equals(insureTrackVO.getRole2()) || "1".equals(insureTrackVO.getRole2()))) {
                    model.addAttribute("issuingCompany", insureTrackVO.getName());
                }
            }
            //排除出单公司
            insuranceCompanyVOS = insuranceCompanyVOS.stream().filter(obj -> "01".equals(obj.getRole1()) || "02".equals(obj.getRole1()) || "03".equals(obj.getRole1())).collect(Collectors.toList());
        }
        model.addAttribute("companys", insuranceCompanyVOS);
        model.addAttribute("companysSize", insuranceCompanyVOS != null ? insuranceCompanyVOS.size() : 0);
        //获取开户行
        getAccountList(model, appDetailProVo);
        //获取投保联系人信息
        HolderForProVO holder = appDetailProVo.getHolder();
        if (holder != null) {
            EduOrgsVO linkMan = queryAuthentEduInfo(holder.getHolderCode());
            model.addAttribute("linkMan", linkMan);
            log.info("投保单预览{} 投保联系人信息完成 投保单号{}", findCode, param.getAppCode());
        }

        //获取保险标的列表
        ResponseEntity<GenericListResponse<DetailVo>> appDetailPro = insuranceObjects(appDetailProVo.getApplicationFormCode());
        if (null != appDetailPro && null != appDetailPro.getBody() && appDetailPro.getBody().getTotal() > 0) {
            List<DetailVo> detailVos = appDetailPro.getBody().getList();
            if (detailVos != null && detailVos.size() > 0) {
                model.addAttribute("extendsDetailVos", detailVos);
                //云南教职工单独获取教师人数
                if (appDetailProVo.getProductCode().equals(PolicyTypeEnum.YN_JZG.getProductCode())) {
                    for (DetailVo vo : detailVos) {
                        for (Map<String, Object> map : vo.getExtendsList()) {
                            if (map.get("fieldValues") != null && !"".equals(map.get("fieldValues"))
                                    && !"invalidation".equals(map.get("fieldValues"))) {
                                Object jzAmount = map.get("fieldValues");
                                model.addAttribute("jzAmount", jzAmount);
                            }
                        }
                    }
                }
                //实责（学校）、校责（学校）计算各人数合计
                if (appDetailProVo.getProductCode().equals(PolicyTypeEnum.STUDENT_SCH.getProductCode())
                        || appDetailProVo.getProductCode().equals(PolicyTypeEnum.TRAINEE_SCH.getProductCode())
                        || appDetailProVo.getProductCode().equals(PolicyTypeEnum.TRAINEE_ENT.getProductCode())) {

                    Integer zcxss = 0;//在册学生数 S_O_000020
                    Integer tbxss = 0;//投保学生数 S_O_000021 实责
                    Integer xz_tbxss = 0;//投保学生数 S_O_000027 校责
                    Integer pqjss = 0;//派遣教师数 S_O_000023
                    Integer bbxrs = 0;//附加被保险人数 S_O_000024
                    Integer wgsrs = 0;//附加实习无过失人数 S_O_000025
                    Integer xfwgs = 0;//附加校方无过失 S_O_000030
                    Integer xwwgs = 0;//附加校外无过失 S_O_000064
                    Integer crb = 0;//附加传染病 S_O_000065

                    Integer S_O_000024 = 0;//每个年级 附加被保险人数 = 附加被保险人数S_O_000024 + 附加实习和附加被保险同时投保人数S_O_000063
                    Integer S_O_000025 = 0;//每个年级 附加实习无过失人数 = 附加实习无过失人数S_O_000025 + 附加实习和附加被保险同时投保人数S_O_000063
                    for (DetailVo vo : detailVos) {
                        S_O_000024 = 0;
                        S_O_000025 = 0;
                        for (Map<String, Object> map : vo.getExtendsList()) {
                            if (map.get("fieldValues") != null && !"".equals(map.get("fieldValues"))
                                    && !"invalidation".equals(map.get("fieldValues"))) {
                                switch (map.get("fieldCode").toString()) {
                                    case "S_O_000020":
                                        zcxss += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000021":
                                        tbxss += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000023":
                                        pqjss += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000024":
                                        bbxrs += getIntegerValue(map.get("fieldValues"));
                                        S_O_000024 += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000025":
                                        wgsrs += getIntegerValue(map.get("fieldValues"));
                                        S_O_000025 += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000027":
                                        xz_tbxss += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000030":
                                        xfwgs += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000063":
                                        bbxrs += getIntegerValue(map.get("fieldValues"));
                                        wgsrs += getIntegerValue(map.get("fieldValues"));
                                        S_O_000024 += getIntegerValue(map.get("fieldValues"));
                                        S_O_000025 += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000064":
                                        xwwgs += getIntegerValue(map.get("fieldValues"));
                                        break;
                                    case "S_O_000065":
                                        crb += getIntegerValue(map.get("fieldValues"));
                                        break;
                                }
                            }
                        }
                        Map<String, Object> bbxrsMap = new HashMap<>();
                        bbxrsMap.put("fieldCode", "bbxrs_num");
                        bbxrsMap.put("fieldValues", S_O_000024);
                        vo.getExtendsList().add(bbxrsMap);
                        Map<String, Object> wgsrsMap = new HashMap<>();
                        wgsrsMap.put("fieldCode", "wgsrs_num");
                        wgsrsMap.put("fieldValues", S_O_000025);
                        vo.getExtendsList().add(wgsrsMap);
                    }
                    model.addAttribute("zcxss", zcxss);
                    model.addAttribute("tbxss", tbxss);
                    model.addAttribute("xz_tbxss", xz_tbxss);
                    model.addAttribute("pqjss", pqjss);
                    model.addAttribute("bbxrs", bbxrs);
                    model.addAttribute("wgsrs", wgsrs);
                    model.addAttribute("xfwgs", xfwgs);
                    model.addAttribute("xwwgs", xwwgs);
                    model.addAttribute("crb", crb);
                    model.addAttribute("extendsDetailVos", detailVos);
                }

                List<Map<String, Object>> extendsList = detailVos.get(0).getExtendsList();//实责（企业）
                model.addAttribute("extendsList", extendsList);
                log.info("投保单预览{} 获取保险标的列表个数{} 投保单号{}", findCode, extendsList.size(), param.getAppCode());
            }
        }

        //根据险种编码展示不同的投保单模板
        String productCode = appDetailProVo.getProductCode();

        //若为实责，企业、学校使用投保单模板不同
        String code = "";
        if (PolicyTypeEnum.TRAINEE_ENT.getProductCode().equals(appDetailProVo.getProductCode())) {
            if (appDetailProVo.getInsuredList() != null
                    && appDetailProVo.getInsuredList().size() > 0
                    && appDetailProVo.getInsuredList().get(0).getCorporation() != null
                    && appDetailProVo.getInsuredList().get(0).getCorporation().getExtendList() != null
                    && appDetailProVo.getInsuredList().get(0).getCorporation().getExtendList().size() > 0) {
                for (ExtendForProVO extendForProVO : appDetailProVo.getInsuredList().get(0).getCorporation().getExtendList()) {
                    String key = extendForProVO.getKey();
                    String value = extendForProVO.getValue();
                    if (key.equals("S_I_000123")) {
                        code = CORPORATION_ENT.equals(value) ? "0" : "1";
                        break;
                    }
                }
            }
        }

        String htmlTemplate = PolicyTypeEnum.getHtmlTemplateByProductCode(productCode, code).getHtmlTemplate();
        log.info("投保单预览{}完成 模板名称{} 投保单号{}", findCode, htmlTemplate, param.getAppCode());

        return htmlTemplate;
    }

    private Integer getIntegerValue(Object value) {
        return value == null || "null".equals(value) ? 0 : Integer.parseInt((String) value);
    }


    @Override
    public String pushStatus(String policyNo, String endorsementNo, Model model, String findCode) {

        log.info("{} 业管推送和结算状态查询 service 开始 保单号->{}，批单号->{}", findCode, policyNo, endorsementNo);

        try {
            GenericListResponse<BmsCommissionVO> commission = bmsClient.commission(CHANNEL_CODE, policyNo, endorsementNo, PAGE_NUM, PAGE_SIZE);
            log.info("{} 业管推送和结算状态查询 佣金凭证查询接口 返回结果->{}", findCode, JsonUtil.object2Json(commission));

            GenericListResponse<BmsPaymentVO> payment = bmsClient.payment(CHANNEL_CODE, policyNo, endorsementNo, PAGE_NUM, PAGE_SIZE);
            log.info("{} 业管推送和结算状态查询 解付状态查询接口 返回结果->{}", findCode, JsonUtil.object2Json(payment));

            GenericListResponse<BmsSettlementVO> settlement = bmsClient.settlement(CHANNEL_CODE, policyNo, endorsementNo, PAGE_NUM, PAGE_SIZE);
            log.info("{} 业管推送和结算状态查询 结算单查询接口 返回结果->{}", findCode, JsonUtil.object2Json(settlement));

            model.addAttribute("commissions", commission.getList());
            model.addAttribute("payments", payment.getList());
            model.addAttribute("settlements", settlement.getList());

            return "bms-push-status";

        } catch (Exception e) {
            e.printStackTrace();
            log.error("{} 业管推送和结算状态查询 异常->{}", findCode, e);
        }
        return null;
    }

}
